package Derivation;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import TopK.EquationTopK;
import Basics.*;

public class SemiNaive 
{
	Map<Atom, HashSet<Body>> provenance = new HashMap<Atom, HashSet<Body>>();
	
	Map<String, Atom> keyMap = new HashMap<String, Atom>();
	
	Program p;
	
	ParseResultsBottomUp parser;
	
	EquationTopK topk;
	
	public SemiNaive (Rule ... irs)
	{
		this.p = new Program(irs);
		this.parser = new ParseResultsBottomUp(this.p, this.provenance, this.keyMap);
	}
	
	
	public SemiNaive (int ik, Rule ... irs) //for online
	{
		this.p = new Program(irs);
		this.topk = new EquationTopK (ik, true);
		this.parser = new ParseResultsBottomUp(this.p, this.provenance, this.keyMap, this.topk);
	}
	
	
	
	public SemiNaive (Program irs)
	{
		this.p = irs;
		this.parser = new ParseResultsBottomUp(this.p, this.provenance, this.keyMap);
	}
	

	
	public SemiNaive (int ik, Program irs) //for online
	{
		this.p = irs;
		this.topk = new EquationTopK (ik, true);
		this.parser = new ParseResultsBottomUp(this.p, this.provenance, this.keyMap, this.topk);
	}
	
	
	public Program getP() 
	{
		return p;
	}


	public void setP(Program p) 
	{
		this.p = p;
	}


	
	public ParseResultsBottomUp getParser() 
	{
		return parser;
	}

	

	public void setHelper(ParseResultsBottomUp iparser)
	{
		this.parser = iparser;
	}


	/*************************************************************************************************************/
	/** Title: SemiNaiveIteration																				
	/** Description: performs one iteration of semi-naive algorithm 			
	/*************************************************************************************************************/
	
	public boolean SemiNaiveIteration (boolean debug, boolean forIntersection, boolean online)
	{
		long startTime = System.currentTimeMillis();
		boolean retVal = parser.ParseResults(forIntersection, online);
		if (false == forIntersection) 
		{
			parser.UpdateDB();
		}
		long end = System.currentTimeMillis();
		if ((end-startTime) > 500) 
		{
			System.out.println("SemiNaiveIteration:: time to update DB + parse results: " + (end-startTime));
			//System.out.println("SemiNaiveIteration:: bodies of dealsWith1(Canada,Andorra) are: " + this.parser.prov.get(this.parser.keyMap.get("dealsWith1(Canada,Andorra)")));
		}
		
		
		//DEBUG
		if (true == debug) 
		{
			System.out.println("atoms added at this step: " + parser.getAddedInstAtoms());
			//System.out.println("provenance at this step: " + parser.getProv());
			System.out.println("size of provenance at this step: " + parser.GetProvSize());
		}
		startTime = System.currentTimeMillis();
		if (true == online) 
		{
			//this.topk.setTreesUpdatedLastIter(this.parser.getProgramDeriver().getAddedInstAtomsInThisIteration());
			this.topk.TopK();
		}
		end = System.currentTimeMillis();
		if ((end-startTime) > 1000) 
		{
			System.out.println("SemiNaiveIteration:: time for top-k: " + (end-startTime));
		}
		
		
		parser.Reset();
		return retVal;
	}
	
	
	
	
	/*************************************************************************************************************/
	/** Title: Run																			
	/** Description: SemiNaiveAlgorithm 			
	/*************************************************************************************************************/
	
	public void Run (boolean debug, boolean forIntersection, boolean online)
	{
		while (false == SemiNaiveIteration(debug, forIntersection, online));
		
		this.parser.getProgramDeriver().addedInstAtomsInThisIteration.clear();
		//this.parser.programDeriver.keyMap.clear();
		//this.parser.programDeriver.provenanceProgram.clear();
		this.parser.getC().SanityCheck();
	}
	
}
